// File: jmcomic-core/src/main/java/dev/jukomu/common/postman/AbstractPostman.java
package dev.jukomu.common.postman;

import dev.jukomu.common.postman.proxy.*;
import dev.jukomu.common.util.Asserts;
import dev.jukomu.common.util.net.IResponse;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * 对应Python的AbstractPostman，Postman接口的抽象实现。
 * 提供了元数据管理、请求参数合并等通用逻辑。
 */
public abstract class AbstractPostman implements Postman {

    // 对应Python的postman_key，用于组件注册
    public static String POSTMAN_KEY = "abstract";

    protected Map<String, Object> metaData; // Postman的元数据，例如headers, cookies, proxies等

    /**
     * 构造函数。
     *
     * @param kwargs 初始化参数Map，将作为元数据存储。
     */
    public AbstractPostman(Map<String, Object> kwargs) {
        Asserts.requireTrue(kwargs != null, "kwargs cannot be null.");
        this.metaData = new HashMap<>(kwargs); // 创建副本，防止外部修改影响内部状态
    }

    /**
     * 创建一个Postman实例。
     * 这是一个工厂方法，方便外部创建实例。
     *
     * @param kwargs 初始化参数Map
     * @return Postman实例
     */
    public static Postman create(Map<String, Object> kwargs) {
        // 在Java中，由于抽象类不能直接实例化，这个create方法需要由具体的实现类来提供。
        // 或者，它可以在Postmans工厂类中被调用，通过反射创建。
        throw new UnsupportedOperationException("AbstractPostman cannot be instantiated directly via create. Use concrete subclasses.");
    }

    @Override
    public IResponse get(String url, Map<String, Object> kwargs) throws Exception {
        Map<String, Object> finalKwargs = beforeRequest(kwargs);
        return getRequestExecutor().get(url, finalKwargs);
    }

    @Override
    public IResponse post(String url, Map<String, Object> kwargs) throws Exception {
        Map<String, Object> finalKwargs = beforeRequest(kwargs);
        return postRequestExecutor().post(url, finalKwargs);
    }

    /**
     * 获取GET请求的实际执行器（例如OkHttp客户端的方法）。
     *
     * @return 执行GET请求的Postman
     */
    protected abstract Postman getRequestExecutor();

    /**
     * 获取POST请求的实际执行器（例如OkHttp客户端的方法）。
     *
     * @return 执行POST请求的Postman
     */
    protected abstract Postman postRequestExecutor();

    /**
     * 在发送请求前的预处理，例如合并kwargs到metaData。
     * 对应Python的before_request。
     *
     * @param kwargs 请求参数Map
     * @return 经过处理后的请求参数Map
     */
    protected Map<String, Object> beforeRequest(Map<String, Object> kwargs) {
        return mergeKwargs(kwargs);
    }

    /**
     * 将传入的kwargs合并到当前Postman的metaData副本中。
     *
     * @param kwargs 外部传入的请求参数
     * @return 合并后的参数Map
     */
    protected Map<String, Object> mergeKwargs(Map<String, Object> kwargs) {
        Map<String, Object> result = new HashMap<>(this.metaData); // 创建metaData的副本
        if (kwargs != null) {
            for (Map.Entry<String, Object> entry : kwargs.entrySet()) {
                // 如果传入的kwargs中值为null，则不覆盖metaData中的值
                if (entry.getValue() != null) {
                    result.put(entry.getKey(), entry.getValue());
                }
            }
        }
        return result;
    }

    @Override
    public <T> T getMetaData(String key, T defaultValue) {
        // 使用AdvancedMap的getOrDefault方法，并处理类型转换
        Object value = metaData.get(key);
        if (value == null) {
            return defaultValue;
        }
        // 由于AdvancedMap的wrapValue逻辑已在JsonUtils中，这里直接返回
        return (T) value; // 假设调用方知道类型或能处理类型转换
    }

    @Override
    public Map<String, Object> getMetaData() {
        return Collections.unmodifiableMap(metaData); // 返回不可修改的Map，防止外部直接修改
    }

    @Override
    public void setItem(String key, Object value) {
        this.metaData.put(key, value);
    }

    @Override
    public Postman getRootPostman() {
        // 默认情况下，如果不是代理，则自身就是根Postman
        return this;
    }

    @Override
    public Postman withFixUrl(String url) {
        return new FixUrlPostman(this, url);
    }

    @Override
    public Postman withRetry(int retryTimes, Class<? extends Postman> clazz) {
        return new RetryPostman(this, retryTimes);
    }

    @Override
    public Postman withMultiPart() {
        return new MultiPartPostman(this);
    }

    @Override
    public Postman withWrapResp(Class<? extends IResponse> clazz) {
        return new WrapRespPostman(this, clazz);
    }

    @Override
    public Postman withRedirectCatching(Class<? extends Postman> clazz) {
        return new RedirectPostman(this);
    }

    @Override
    public Postman copy() {
        // 实现深拷贝
        return null; // 具体的拷贝逻辑将在子类中实现，因为它依赖于子类的构造函数
    }
}